package com.niiwoo.civet.mobile.controller.lanmao;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.google.common.base.Splitter;
import com.niiwoo.tripod.base.annotation.ProfileSpecified;
import com.niiwoo.tripod.base.component.AsyncHttpClients;
import com.niiwoo.tripod.base.helper.NetTools;
import com.niiwoo.tripod.lanmao.response.LanMaoNotifyResponse;
import com.niiwoo.tripod.web.annotation.AuthIgnore;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletResponse;
import java.net.Inet4Address;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Future;

/**
 * Created by zhangwanli on 2017/11/10.
 */
@Controller
@RequestMapping("/lanmao")
@ProfileSpecified
@Profile({"default", "dev-online", "test"})
@AuthIgnore
@Api(hidden = true)
public class DevProfileLanMaoNotifyDispatchController extends LanMaoNotifyDispatchController {
    private static final Logger logger = LoggerFactory.getLogger(DevProfileLanMaoNotifyDispatchController.class);

    @Autowired
    private AsyncHttpClients asyncHttpClients;
    @Autowired
    private ServerProperties serverProperties;
    private String local_addr = NetTools.getLocalAddress(address -> address instanceof Inet4Address).getHostAddress();

    @RequestMapping("/notify")
    @ApiOperation(value = "懒猫异步通知接收", hidden = true)
    @ResponseBody
    @Override
    public String receiveNotify(LanMaoNotifyResponse notifyResponse, HttpServletResponse servletResponse) throws Exception {
        logger.info("received lanmao notify:{}", JSON.toJSONString(notifyResponse, SerializerFeature.UseSingleQuotes));
        String respData = notifyResponse.getRespData();
        JSONObject json = JSON.parseObject(respData);
        String dispatchNo = parseDispatchNo(json);
        logger.info("received lanmao notify, dispatchNo={}", dispatchNo);
        if (dispatchNo.indexOf("-") > 0) {
            List<String> list = Splitter.on("-").splitToList(dispatchNo);
            String ip = list.get(0).replaceAll("_", "\\.");
            String port = list.get(1);
            if (local_addr.equals(ip)) {
                return super.receiveNotify(notifyResponse, servletResponse);
            } else {
                dispatch(notifyResponse, servletResponse, ip, port);
                return null;
            }
        } else {
            return super.receiveNotify(notifyResponse, servletResponse);
        }
    }

    private String parseDispatchNo(JSONObject json) {
        String dispatchNo = json.getString("requestNo");
        if (dispatchNo == null) {
            JSONArray details = json.getJSONArray("details");
            if (details != null) {
                dispatchNo = details.getJSONObject(0).getString("asyncRequestNo");
            } else {
                dispatchNo = "";
            }
        }
        return dispatchNo;
    }

    @RequestMapping("/callback")
    @ApiOperation(value = "懒猫异步通知接收", hidden = true)
    @Override
    public ModelAndView receiveCallback(LanMaoNotifyResponse notifyResponse, HttpServletResponse response) throws Exception {
        String respData = notifyResponse.getRespData();
        JSONObject json = JSON.parseObject(respData);
        String requestNo = json.getString("requestNo");
        logger.info("received lanmao notify, requestNo={}", requestNo);
        if (requestNo.indexOf("-") > 0) {
            List<String> list = Splitter.on("-").splitToList(requestNo);
            String ip = list.get(0).replaceAll("_", "\\.");
            String port = list.get(1);
            if (local_addr.equals(ip)) {
                return super.receiveCallback(notifyResponse, response);
            } else {
                response.setContentType("text/html;charset=UTF-8");
                dispatch(notifyResponse, response, ip, port);
                return null;
            }
        } else {
            return super.receiveCallback(notifyResponse, response);
        }
    }

    private void dispatch(LanMaoNotifyResponse notifyResponse, HttpServletResponse response, String ip, String port) throws Exception {
        HttpResponse httpResponse = dispatchToRealReceiver(ip, port, notifyResponse);
        Header[] allHeaders = httpResponse.getAllHeaders();
        for (Header header : allHeaders) {
            String headerName = header.getName();
            if (!response.containsHeader(headerName)) {
                response.addHeader(headerName, header.getValue());
            }
        }
        response.setStatus(httpResponse.getStatusLine().getStatusCode());
        response.getWriter().print(EntityUtils.toString(httpResponse.getEntity()));
    }

    private HttpResponse dispatchToRealReceiver(String ip, String port, LanMaoNotifyResponse notifyResponse) throws Exception {
        Map<String, Object> map = new HashMap<>();
        map.put("serviceName", notifyResponse.getServiceName());
        map.put("platformNo", notifyResponse.getPlatformNo());
        map.put("responseType", notifyResponse.getResponseType());
        map.put("keySerial", notifyResponse.getKeySerial());
        map.put("respData", notifyResponse.getRespData());
        map.put("sign", notifyResponse.getSign());

        String url = null;
        if ("NOTIFY".equals(notifyResponse.getResponseType().name())) {
            url = "http://" + ip + ":" + port + serverProperties.getContextPath() + "/lanmao/notify";
        } else if ("CALLBACK".equals(notifyResponse.getResponseType().name())) {
            url = "http://" + ip + ":" + port + serverProperties.getContextPath() + "/lanmao/callback";
        } else {
            logger.error("ResponseType解析异常：{}", JSON.toJSON(notifyResponse));
        }
        logger.info("dispath notify to {}", url);
        Future<HttpResponse> future = asyncHttpClients.formPost(url, map, null);
        return future.get();
    }

}
